package com.example.game_community.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.game_community.entity.Comment;
import com.example.game_community.entity.User;
import com.example.game_community.mapper.CommentMapper;
import com.example.game_community.service.CommentService;
import com.example.game_community.service.UserService;
import com.example.game_community.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
/**
 * 评论服务实现类
 * <p>具体实现评论相关的业务逻辑，包括回复创建、评论树构建等核心功能</p>
 * <p>实现规范：
 * <ul>
 *   <li>所有数据库操作通过MyBatis Plus Mapper实现</li>
 *   <li>树形结构构建使用递归算法</li>
 *   <li>用户信息绑定采用批量查询优化</li>
 * </ul>
 * </p>
 *
 * @author 社区开发团队
 * @version 1.1
 * @since 2024-01-01
 */
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    UserService userService;

    /**
     * 实现评论回复创建
     *
     * @param parentId 父级评论ID（必须存在）
     * @param comment  包含用户ID、内容等属性的评论对象
     * @return 携带新创建评论数据的响应结果
     */
    @Override
    /**
     * 创建评论回复
     * @param parentId 必须存在的父级评论ID（大于0的Long类型）
     * @param comment 包含以下必须属性的评论对象：
     *               <ul>
     *                 <li>userId - 当前用户ID</li>
     *                 <li>content - 非空且长度不超过500字符</li>
     *               </ul>
     * @return 统一响应结果：
     *         <ul>
     *           <li>success: 包含新评论对象</li>
     *           <li>error: 当父评论不存在时返回错误信息</li>
     *         </ul>
     * @throws IllegalArgumentException 当参数不符合要求时抛出
     */
    public Result<Comment> createReply(Long parentId, Comment comment) {
        // 业务逻辑实现...
        Comment parent = this.getById(parentId);
        if (parent == null) {
            return Result.error("没有该评论");
        }

        Comment reply = new Comment();
        reply.setContent(comment.getContent());
        reply.setUserId(comment.getUserId());
        reply.setCommentTime(LocalDateTime.now());
        reply.setParentId(parentId);
        this.baseMapper.insert(reply);
        return Result.success("回复成功！");
    }


    /**
     * 构建帖子评论树形结构
     *
     * @param postId 必须存在的帖子ID（大于0的Long类型）
     * @return 结构化评论列表，包含：
     *         <ul>
     *           <li>嵌套子评论（children字段）</li>
     *           <li>关联用户信息（user字段）</li>
     *         </ul>
     * 实现步骤：
     * 1. 查询帖子所有平级评论
     * 2. 批量绑定用户信息（N+1查询优化）
     * 3. 构建父评论映射表
     * 4. 递归构造树形结构
     */
    @Override
    public Result<List<Comment>> getCommentTree(Long postId) {
        // 获取所有相关评论
        List<Comment> comments = lambdaQuery()
                .eq(Comment::getPostId, postId).list();

        bindUserInfo(comments);

        Map<Long, List<Comment>> commentMap = comments
                .stream()
                .filter(c -> c.getParentId() != null)
                .collect(Collectors.groupingBy(Comment::getParentId));

        List<Comment> commentTree = comments.stream()
                .filter(c -> c.getParentId() == null)
                .map(c -> buildNode(c, commentMap))
                .collect(Collectors.toList());

        return Result.success(commentTree); // 将结果包装到Result对象中
    }

    /**
     * 批量绑定用户信息到评论对象
     *
     * @param comments 需要绑定用户信息的评论列表（非空）
     *                 实现策略：
     *                 1. 提取评论中所有用户ID
     *                 2. 批量查询用户信息
     *                 3. 构建用户ID到用户对象的映射
     *                 4. 为每个评论设置关联用户
     */
    private void bindUserInfo(List<Comment> comments) {
        // 检查评论列表是否为空
        if (comments == null || comments.isEmpty()) {
            return;
        }

        Set<Long> userIds = comments.stream()
            .map(Comment::getUserId)
            .collect(Collectors.toSet());

        // 检查用户ID集合是否为空
        if (userIds.isEmpty()) {
            return;
        }

        Map<Long, User> userMap = userService.listByIds(userIds)
            .stream()
            .collect(Collectors.toMap(User::getId, Function.identity()));

        comments.forEach(c -> c.setUser(userMap.get(c.getUserId())));
    }

    /**
     * 递归构建评论树节点
     *
     * @param comment    当前节点评论对象（非空）
     * @param commentMap 子评论映射表（parentId -> 子评论列表）
     * @return 包含子节点结构的评论对象
     * 算法说明：
     * 1. 从映射表获取当前评论的直接子评论
     * 2. 深度优先遍历子评论列表
     * 3. 为每个子评论递归构建子树
     * 4. 设置children字段形成树形结构
     */
    private Comment buildNode(Comment comment, Map<Long, List<Comment>> commentMap) {

        List<Comment> children = commentMap.getOrDefault(comment.getId(), Collections.emptyList());

        comment.setChildren(children.stream().map(c -> buildNode(c, commentMap)).collect(Collectors.toList()));
        return comment;
    }

}
